#ifndef __CHARSCREEN_HPP
#define __CHARSCREEN_HPP

#include "../model/base/Graphic.hpp"
#include "base/Screen.hpp"

#include <cstring>
#include <cstdio>

using namespace std;

namespace view {

/**
 * 字符像素屏幕类
 */ 
class CharScreen: public base::Screen<char> {
	
	public:typedef model::base::graphic::Pixel<char> Pixel;
	public:typedef base::Screen<Pixel>               Base;
	
	protected:       const unsigned   size[4]; //x, y, lineMemorySize, memorySize
	private:  static const unsigned   X = 0, Y = 1, LINEMEM = 2, MEMORY = 3;
	protected:             char *     buffer;  //row, col
	
	/**
	 * 创建一个字符像素屏幕对象的构造器 
	 * @param sizeX 屏幕宽度(像素)
	 * @param sizeY 屏幕高度(像素) 
	 */
	public:CharScreen(unsigned sizeX, unsigned sizeY): 
		size{sizeX, sizeY, 2*sizeX, 2*sizeX * sizeY}, buffer(new char[size[MEMORY]]) {
		buffer[size[MEMORY] - 1] = '\0';
		clear();
	}
	
	private:void unuse(void) {
		buffer = nullptr;
	}
	
	public:CharScreen(const CharScreen& another): size{another.size[0], another.size[1], another.size[2], another.size[3]}, buffer(new char[size[MEMORY]]) {
		memcpy(buffer, another.buffer, size[MEMORY] * sizeof(char));
	} 
	
	public:CharScreen(CharScreen&& another) noexcept: size{another.size[0], another.size[1], another.size[2], another.size[3]}, buffer(another.buffer) {
		another.unuse();
	}
	
	/*
	 * 析构器 
	 */ 
	public:~CharScreen(void) {
		delete buffer;
	}
	
	/**
	 *  修复 
	 */
	//@Override
	public:void fix(void) {
		memset(buffer, ' ', size[MEMORY]);
		//在每行尾部添加\n 
		for(unsigned line = size[LINEMEM], end = size[MEMORY] - 1, step = size[LINEMEM]; line <= end; line += step) buffer[line - 1] = '\n';
		buffer[size[MEMORY] - 1] = '\0';
	}
	
	/**
	 *  清屏 
	 */
	//@Override
	public:void clear(void) {
		memset(buffer, ' ', size[MEMORY] - 1);
		//在每行尾部添加\n 
		for(unsigned line = size[LINEMEM], end = size[MEMORY] - 1, step = size[LINEMEM]; line <= end; line += step) buffer[line - 1] = '\n';
	}

	/**
	 * 设置像素点
	 * @param x 像素点的x坐标 
	 * @param y 像素点的y坐标
	 * @param pixel 表示像素点的字符
	 */ 
	//@Override
	public:void setPixel(const model::base::graphic::Pixel<char>& gPixel) {
		/*
		0 0123
		1 4567
		2 89ab
		*/

		Integer y = size[Y] - gPixel.getY() - 1;
		Integer offset = size[LINEMEM] * y + 2 * gPixel.getX();
		if(offset < 0  || (unsigned)gPixel.getX() >= size[X] ||  offset >= (Integer)size[MEMORY]) return;

		buffer[offset] = gPixel.getPixel();
	}
	
	/**
	 * 扫描输出屏幕 
	 */
	//@Override
	public:void scan(ostream& ost) const {
		ost<<buffer<<flush;
	}
};
};

#endif
